<?php
namespace zake\foundation\able\traits;

use zake\foundation\reactor\Reactor;
use zake\foundation\stream\BufferWriteStream;
use zake\foundation\stream\WriteStream;

/**
 * Trait WriteBufferTrait
 * @package zake\foundation\able\traits
 *
 * @author liu.bin 2020-04-28 17:02
 */
trait WriteBufferTrait
{

    /**
     * @var int
     */
    protected $w_pos = 0;


    /**
     * @var string
     */
    protected $writeBuffer = "";


    /**
     * 获取准备发送的数据，不刷新写缓冲区
     *
     * @return string
     * @author liu.bin 2020-03-24 16:25
     */
    public function getWriteBuffer()
    {
        return $this->writeBuffer;
    }


    /**
     * 将数据写入 bufferStream 的 writeBuffer,并设置写监听
     *
     * @param string $sendData
     * @param null|\Closure $callback
     * @param array $param [encode->true]
     * @return int
     *
     * @author liu.bin 2020-03-24 14:56
     */
//    public function writeBuffer($sendData,$callback=null,$param=[])
//    {
//        if($this->isCloseWriteResource()){
//            return -1;
//        }
//        $sendLen   = $this->pushWriteBuffer($sendData,($param['encode']??true));
//        if(false === $sendLen){
//            return -1;
//        }
//        // 添加写监听
//        Reactor::addWriteListener($this,function() use ($callback,$sendLen){
//            $buffer = $this->shiftWriteBuffer();
//            $size   = $this->write($buffer,['recursion'=>false]);
//            if($size <= 0){
//                // 发送错误
//                Reactor::removeWriteListener($this);
//            }
//            if($size >= $sendLen){
//                // 发送完成
//                Reactor::removeWriteListener($this);
//                if($callback instanceof \Closure){
//                    $callback();
//                }
//            }else{
//                // 未发完
//                $this->pushWriteBuffer(substr($buffer,$size),false);
//            }
//        });
//        return $sendLen;
//    }




    /**
     * 先发送数据，如果数据没有发送完整，加入事件监听再发送
     * @param string $sendData
     * @param null|\Closure $callback
     * @param null|\Closure $errorCallback
     *
     * @return int|false
     *
     * @author liu.bin 2020-03-24 14:56
     */
    public function writeBuffer($sendData,$callback=null,$errorCallback=null)
    {

        $writeLength    = strlen($sendData);
        if(empty($writeLength) || $writeLength > BufferWriteStream::WRITE_MAX_LENGTH){
            if($errorCallback instanceof \Closure){
                $errorCallback();
            }
            return -1;
        }


        // 发送数据
        $sendSize = $this->write($sendData,WriteStream::MODE_ONCE);
        if($sendSize >= $writeLength){
            if($callback instanceof \Closure){
                $callback();
            }
            return $sendSize;
        }

        // 没有发送完成，加入写监听等待可写时发送
        $leftLength   = $writeLength - $sendSize;
        $leftBuffer   = substr($sendData,$sendSize);
        $this->pushWriteBuffer($leftBuffer);

        // 添加写监听
        Reactor::addWriteListener($this,function() use ($callback,$leftLength,$errorCallback){
            $buffer = $this->shiftWriteBuffer();
            $size   = $this->write($buffer,WriteStream::MODE_ONCE);
            if($size <= 0){
                // 发送错误
                Reactor::removeWriteListener($this);
                if($errorCallback instanceof \Closure){
                    $errorCallback();
                }
            }
            if($size >= $leftLength){
                // 发送完成
                Reactor::removeWriteListener($this);
                if($callback instanceof \Closure){
                    $callback();
                }
            }else{
                // 未发完,将数据缓冲
                $this->pushWriteBuffer(substr($buffer,$size));
            }
        });

        //
        return $writeLength;
    }


    /**
     * 将数据写入读缓冲区
     *
     * @param string $buffer
     * @param bool $encode 是否进行编码
     * @return int|false
     * @author liu.bin 2020-03-24 11:01
     */
    public function pushWriteBuffer($buffer)
    {
        $pushLen = strlen($buffer);
        if($this->w_pos + $pushLen > BufferWriteStream::WRITE_MAX_LENGTH){
            return false;
        }
        $this->writeBuffer .= $buffer;
        $this->w_pos += $pushLen;
        return $pushLen;
    }


    /**
     * 读取写缓冲区的数据并刷新缓冲区
     *
     * 如果读取的长度不够，则不会读取，返回空字符串
     *
     * @param int $size 需要读取缓冲区的长度
     * @return string
     * @author liu.bin 2020-03-27 10:26
     */
    public function shiftWriteBuffer($size=null)
    {
        if(is_null($size) || $size >= $this->w_pos){
            $shiftBuffer        = $this->writeBuffer;
            $this->writeBuffer  = "";
            $this->w_pos        = 0;
        }else{
            $buffer             = $this->writeBuffer;
            $shiftBuffer        = substr($buffer,0,$size);
            $this->writeBuffer  = substr($buffer,$size);
            $this->w_pos        = $this->w_pos - $size;
        }

        return $shiftBuffer;
    }


    /**
     *
     * @return int
     *
     * @author liu.bin 2020-04-03 10:43
     */
    public function getWPos()
    {
        return $this->w_pos;
    }

}